package com.ll.domain.classbase.biz.impl;

import com.ll.app.api.req.SignupReqDTO;
import com.ll.base.enums.ResultCodeEnum;
import com.ll.domain.classbase.base.ClassBaseService;
import com.ll.domain.classbase.convert.SignupConvert;
import com.ll.domain.classbase.base.CourseBaseService;
import com.ll.domain.classbase.base.SignupBaseService;
import com.ll.domain.classbase.biz.SignupDomainService;
import com.ll.dal.po.CoursePO;
import com.ll.dal.po.SignupPO;
import com.ll.domain.classbase.enums.CourseTypeEnum;
import com.ll.domain.dingtalk.base.DingTalkUserBaseService;
import com.ll.domain.user.base.UserBaseService;
import com.ll.domain.classbase.dto.SignupDTO;
import com.ll.domain.user.dto.UserDTO;
import com.ll.app.api.req.ListSignupReqDTO;
import com.ll.app.api.req.SignupApplyReqDTO;
import com.ll.domain.classbase.enums.SingupStatusEnum;
import com.ll.domain.dingtalk.utils.AccessTokenUtil;
import com.ll.base.util.ListUtil;
import com.ll.base.dto.ApiResultDTO;
import com.ll.domain.user.enums.RoleEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class SignupDomainServiceImpl implements SignupDomainService {

    private final CourseBaseService courseBaseService;
    private final SignupBaseService signupBaseService;
    private final DingTalkUserBaseService dingTalkUserBaseService;
    private final UserBaseService userBaseService;
    private final ClassBaseService classBaseService;
    private final Integer JF_COURSE = 10;

    @Override
    public ApiResultDTO apply(SignupApplyReqDTO reqDTO) {
        Long courseId = reqDTO.getCourseId();
        CoursePO coursePO = courseBaseService.getById(courseId);
        if (coursePO == null) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_NOT_EXIST);
        }

        if(CourseTypeEnum.积分训练 == coursePO.getType()){
            UserDTO userDTO = userBaseService.getByDingUserId(reqDTO.getDingTalkUserId());
            if(JF_COURSE.compareTo(userDTO.getIntegral()) > 0){
                return ApiResultDTO.failure(ResultCodeEnum.INTEGRAL_ERROR);
            }
        }

        if (!coursePO.getStatus().checkCanApply()) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_STATUS_EXCEPTION.getCode(),
                    "当前训练状态为[" + coursePO.getStatus() + "]不可报名");
        }

        if (!coursePO.checkCanApply()) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_APPLY_MAX);
        }


        if(!classBaseService.checkStudent(reqDTO.getDingTalkUserId()) && coursePO.getType() == CourseTypeEnum.学员训练){
            return ApiResultDTO.failure(ResultCodeEnum.SIGNUP_STATUS_EXCEPTION.getCode(),
                    "您不是正在开班的学生");
        }

        SignupPO signupPO = signupBaseService.getByUserIdAndCourse(reqDTO.getDingTalkUserId(), courseId);
        if (signupPO != null && signupPO.getStatus() != SingupStatusEnum.未报名) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_STATUS_EXCEPTION.getCode(),
                    "已经报名过了请不要重复报名");
        }

        if (signupPO != null) {
            signupBaseService.updateStatus(signupPO.getId(), SingupStatusEnum.已报名);
        }else{
            signupPO = SignupPO.builder()
                    .createTime(new Date())
                    .dingTalkUserId(reqDTO.getDingTalkUserId())
                    .courseId(courseId)
                    .teacher(coursePO.getTeacher())
                    .status(SingupStatusEnum.已报名)
                    .build();
            signupBaseService.save(signupPO);
        }
        courseBaseService.apply(coursePO.getId());
        if(CourseTypeEnum.积分训练 == coursePO.getType()){
            userBaseService.addIntegral(reqDTO.getDingTalkUserId(), -10);
        }
        return ApiResultDTO.success();
    }

    @Override
    public ApiResultDTO cancelApply(SignupApplyReqDTO reqDTO) {
        CoursePO coursePO = courseBaseService.getById(reqDTO.getCourseId());
        if (coursePO == null) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_NOT_EXIST);
        }

        if (!coursePO.getStatus().checkCanCancelApply()) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_STATUS_EXCEPTION.getCode(),
                    "当前训练状态为[" + coursePO.getStatus() + "]不可取消报名");
        }
        SignupPO po = signupBaseService.getByUserIdAndCourse(reqDTO.getDingTalkUserId(), reqDTO.getCourseId());
        if (po == null) {
            return ApiResultDTO.success();
        }
        signupBaseService.updateStatus(po.getId(), SingupStatusEnum.未报名);

        courseBaseService.cancelApply(coursePO.getId());
        return ApiResultDTO.success();
    }

    @Override
    public ApiResultDTO signup(SignupReqDTO reqDTO) {
        CoursePO coursePO = courseBaseService.getById(reqDTO.getCourseId());
        if (coursePO == null) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_NOT_EXIST);
        }



        if (coursePO.getStatus().checkSignup()) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_STATUS_EXCEPTION.getCode(),
                    "当前训练状态为[" + coursePO.getStatus() + "]不可签到");
        }
        SignupPO po = signupBaseService.getByUserIdAndCourse(reqDTO.getStudentUserId(), reqDTO.getCourseId());
        if (po == null) {
            return ApiResultDTO.success();
        }

        if (!po.getStatus().checkCanSingup()) {
            return ApiResultDTO.failure(ResultCodeEnum.COURSE_STATUS_EXCEPTION.getCode(),
                    "当前报名状态为[" + po.getStatus() + "]不可签到");
        }
        signupBaseService.updateStatus(po.getId(), SingupStatusEnum.已签到);
        if(CourseTypeEnum.积分训练 == coursePO.getType()){
            userBaseService.addIntegral(po.getDingTalkUserId(), 5);
        }else{
            userBaseService.addIntegral(po.getDingTalkUserId(), 10);
        }
        return ApiResultDTO.success();
    }

    @Override
    public ApiResultDTO queryListByCourseId(ListSignupReqDTO reqDTO) {
        List<SignupPO> signupPOS = signupBaseService.queryListByCourseId(reqDTO.getCourseId());
        List<SignupDTO> signupDTOS = ListUtil.toList(signupPOS, SignupConvert::PO2DTO);
        String token = AccessTokenUtil.getToken();
        signupDTOS.forEach(r->{
            UserDTO userDTO = dingTalkUserBaseService.getByUserId(token, r.getDingTalkUserId());
            r.setStudentName(userDTO.getUserName());
        });
        return ApiResultDTO.success(signupDTOS);
    }

    @Override
    public ApiResultDTO list(ListSignupReqDTO reqDTO) {
        List<SignupPO> signupPOS = signupBaseService.queryList(reqDTO);
        List<SignupDTO> signupDTOS = ListUtil.toList(signupPOS, SignupConvert::PO2DTO);
        String token = AccessTokenUtil.getToken();
        signupDTOS.forEach(r->{
            UserDTO userDTO = dingTalkUserBaseService.getByUserId(token, r.getDingTalkUserId());
            r.setStudentName(userDTO.getUserName());
        });
        return ApiResultDTO.success(signupDTOS);
    }
}
